//package com.zy.common.core.lock;
//
//
//import com.zy.common.core.enums.ErrorEnums;
//import com.zy.common.utils.ApplicationUtils;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.ArrayUtils;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.Signature;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.springframework.context.ApplicationContext;
//import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
//import org.springframework.core.annotation.AnnotationUtils;
//import org.springframework.core.annotation.Order;
//import org.springframework.expression.ExpressionParser;
//import org.springframework.expression.spel.standard.SpelExpressionParser;
//import org.springframework.expression.spel.support.StandardEvaluationContext;
//import org.springframework.stereotype.Component;
//import org.springframework.validation.BindException;
//
//import java.lang.reflect.Method;
//import java.util.concurrent.TimeUnit;
//
///**
// * @author : zy
// * @version V1.0
// * @Description: 分布式锁切面
// * @date Date : 2023年06月29日 10:34 上午
// */
//
//@Slf4j
//@Component
//@Aspect
//@Order(0) // 一般情况应该比 @transaction 优先级高
//public class LockAspect {
//
//
//    /**
//     * 定义缓存逻辑
//     *
//     * @throws Throwable
//     */
//    @Around("@annotation(com.zy.common.core.lock.Locks)")
//    public Object locks(ProceedingJoinPoint pjp) throws Throwable {
//        Method method = getMethod(pjp);
//        Locks lock = method.getAnnotation(Locks.class);
//        Lock[] locks = lock.value();
//
//        // 获取注解详情
//        if (ArrayUtils.isEmpty(locks)) {
//            throw new BindException(ErrorEnums.SYSTEM_ERROR, "Locks 注解配置异常");
//        }
//
//        RedissonClient redisson = ApplicationUtils.getBean(RedissonDistributedLocker.class).getRedissonClient();
//        int longestExpireTime = 0;
//        int longestWaitTime = 0;
//        RLock[] rLocks = new RLock[locks.length];
//        for (int k = 0; k < locks.length; k++) {
//            Lock cacheLock = locks[k];
//            String key = cacheLock.key();
//            key = getSPELValue(key, pjp);
//            int retry = cacheLock.retry();
//            int seconds = cacheLock.expireSeconds();
//            int interval = cacheLock.retryIntervalMills();
//            String errorMsg = cacheLock.errorMsg();
//
//            rLocks[k] = redisson.getLock(key);
//            if (longestWaitTime < retry * interval) {
//                longestWaitTime = retry * interval;
//            }
//            if (longestExpireTime < seconds) {
//                longestExpireTime = seconds;
//            }
//        }
//
//        // 获取多重锁
//        RLock redissonLock = redisson.getMultiLock(rLocks);
//        try {
//            redissonLock.tryLock(longestWaitTime, longestExpireTime * 1000, TimeUnit.MILLISECONDS);
//        } catch (Exception e) {
//            log.info("Locks|error:{}", e.getMessage(), e);
//            throw new BindException(ErrorEnums.SYSTEM_ERROR, "系统其他操作正在进行中,请稍后重试");
//        } finally {
//            redissonLock.unlock();
//        }
//
//        // 执行方法
//        try {
//            return pjp.proceed();
//        } catch (Exception e) {
//            log.info("Locks|error:{}", e.getMessage(), e);
//            throw e;
//        } finally {
//            redissonLock.unlock();
//        }
//    }
//
//    /**
//     * 定义缓存逻辑
//     *
//     * @throws Throwable
//     */
//    @Around("@annotation(com.zy.common.core.lock.Lock)")
//    public Object lock(ProceedingJoinPoint pjp) throws Throwable {
//        Method method = getMethod(pjp);
//
//        Lock cacheLock = AnnotationUtils.findAnnotation(method, Lock.class);
//        String key = cacheLock.key();
//        key = getSPELValue(key, pjp);
//        int retry = cacheLock.retry();
//        int seconds = cacheLock.expireSeconds();
//        int interval = cacheLock.retryIntervalMills();
//        String errorMsg = cacheLock.errorMsg();
//
//        log.info("Locker|{}", key);
//        //获取锁的时候进行间隔100ms的重试
//        boolean ownLock = false;
//        if (retry < 1) {
//            retry = 1;
//        }
//        for (int i = 0; i < retry; i++) {
//            if (lock(key, interval, seconds)) {
//                ownLock = true;
//                break;
//            }
//        }
//        if (!ownLock) {
//            log.info("Locker|error:{}", errorMsg);
//            throw new BindException(ErrorEnums.SYSTEM_ERROR, errorMsg);
//        } else {
//            if (log.isDebugEnabled()) {
//                log.debug("Locker|success:{}", key);
//            }
//        }
//
//        // 执行方法
//        try {
//            return pjp.proceed();
//        } catch (Exception e) {
//            log.info("WMS Locker|error:{}",e.getMessage(),e);
//            throw e;
//        }finally {
//            unlock(key);
//        }
//    }
//
//    /**
//     * 获取被拦截方法对象
//     * <p>
//     * MethodSignature.getMethod() 获取的是顶层接口或者父类的方法对象
//     * 而缓存的注解在实现类的方法上
//     * 所以应该使用反射获取当前对象的方法对象
//     */
//    private Method getMethod(ProceedingJoinPoint pjp) {
//        Method method = null;
//
//        Signature signature = pjp.getSignature();
//        MethodSignature methodSignature = (MethodSignature) signature;
//        Method targetMethod = methodSignature.getMethod();
//
//        try {
//            method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), targetMethod.getParameterTypes());
//        } catch (NoSuchMethodException | SecurityException e) {
//            log.info("PJP Method|error:{}", e.getMessage(), e);
//        }
//        return method;
//    }
//
//    private Boolean lock(String key, int retryIntervalMills,int seconds){
//        DistributedLocker locker = ApplicationUtils.getBean(DistributedLocker.class);
//        return locker.tryLock(key,TimeUnit.MILLISECONDS,retryIntervalMills,seconds * 1000);
//    }
//
//    private Boolean unlock(String lockKey){
//        DistributedLocker locker = ApplicationUtils.getBean(DistributedLocker.class);
//        locker.unlock(lockKey);
//        return true;
//    }
//
//    /**
//     * 获取缓存的key
//     * key 定义在注解上，支持SPEL表达式
//     *
//     * @param pjp
//     * @return
//     * @throws NoSuchMethodException
//     */
//    private String getSPELValue(String key, ProceedingJoinPoint pjp) throws NoSuchMethodException {
//        //获取被拦截方法参数名列表(使用Spring支持类库)
//        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
//        Method method = getMethod(pjp);
//        String[] paraNameArr = u.getParameterNames(method);
//        Object[] args = pjp.getArgs();
//        //使用SPEL进行key的解析
//        ExpressionParser parser = new SpelExpressionParser();
//        //SPEL上下文
//        StandardEvaluationContext context = new StandardEvaluationContext();
//
//
//        //把方法参数放入SPEL上下文中
//        if (log.isDebugEnabled()) {
//            log.debug("SPEL-key:{}", key);
//        }
//        for (int i = 0; i < paraNameArr.length; i++) {
//            context.setVariable(paraNameArr[i], args[i]);
//        }
//        if (null != paraNameArr && paraNameArr.length > 0) {
//            key = parser.parseExpression(key).getValue(context, String.class);
//        }
//        return key;
//    }
//}
